/*
    DIMVisual-KAAPI, the DIMVisual bundle for KAAPI trace files
    Copyright (c) 2008 Lucas Mello Schnorr <schnorr@gmail.com>

    This file is part of DIMVisual-KAAPI.

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/
#include "KAAPIConverter.h"
#include <kaapi> /* for the trace and level stuff (identifier) */

NSMutableArray *tobetreated = [NSMutableArray array];

@implementation KAAPIConverter (Kernel)
- (id) convertEventKernelThreadRetRsteal: (GEvent *) event
{
        NSMutableArray *ret = [NSMutableArray array];
        if (conversionType == Thread){
                return ret;
        }

        GFields *f = [event fields];
        NSString *retval = [f fieldWithSimpleStringKey:@"retval"];
        NSString *victim = [f fieldWithSimpleStringKey:@"gidvictim"];

	/* verifying if the steal was ok or not */
	NSString *value;
        if (atoi([retval cString]) == 0){
		value = @"RetRsteal-0";
        }else{
		value = @"RetRsteal-1";
	}
	[ret addObject: [self addPajeSetState: @"RUNNING"
		toState: @"State" time: time container: container]];

	NSString *sourcecontainer = container;
        static int ckey = 0;
        NSString *key = [NSString stringWithFormat: @"ws%d", ckey++];

        NSString *spcontainer = [provider identifierForEntity: 
		[NSArray arrayWithObjects: @"0", nil] 
		ids: [NSArray arrayWithObjects: @"0", nil]];
	
        NSString *victimhostname = [mappingGidHostname objectForKey: victim];

	if (victimhostname == nil){
		static int count = 1;
		//exception? TODO
		NSString *str;
		str = [NSString stringWithFormat: @"KAAPIConverter (%s,%d): "
		        "event is stealing from a victim that was not "
			"created till now (this is probably a synchronization "
			"problem).", __FUNCTION__, __LINE__];
//		[[NSException exceptionWithName: @"DIMVisual-KAAPIConverter"
//		        reason: str userInfo: nil] raise];
		NSLog (@"WARNING(%d)!! %@ (Trace time=%@)", count++, str, time);

		NSMutableDictionary *miss = [NSMutableDictionary dictionary];
		[miss setObject: time forKey: @"time"];
		[miss setObject: sourcecontainer forKey: @"sourcecontainer"];
		[miss setObject: spcontainer forKey: @"container"];
		[miss setObject: key forKey: @"key"];
		[miss setObject: victim forKey: @"victim"];
		[miss setObject: value forKey: @"value"];

//		[tobetreated addObject: miss];
	}else{

	        NSString *vic2;
		vic2 = [NSString stringWithFormat: @"%@_at_%@",
			victim, victimhostname];

	        NSString *destcontainer = [provider identifierForEntity: 
			[NSArray arrayWithObjects: @"gid", nil] 
			ids: [NSArray arrayWithObjects: vic2, nil]];

		PajeStartLink *sl;
		sl = [[PajeStartLink alloc] init];
		[sl setTime: time];
		[sl setContainer: spcontainer];
		[sl setSourceContainer: sourcecontainer];
		[sl setEntityType: [provider aliasToName:@"Remote_Steal"]];
		[sl setValue: value];
		[sl setKey: key];
		[ret addObject: sl];
		[sl release];
		
		PajeEndLink *el;
		el = [[PajeEndLink alloc] init];
		[el setTime: time];
		[el setContainer: spcontainer];
		[el setDestContainer: destcontainer];
		[el setEntityType: [provider aliasToName:@"Remote_Steal"]];
		[el setValue: value];
		[el setKey: key];
		[ret addObject: el];
		[el release];
	}

	/* check tobetreated */
	if ([tobetreated count] != 0 && 0){
		unsigned int i;
		for (i = 0; i < [tobetreated count]; i++){
			NSDictionary *miss = [tobetreated objectAtIndex: i];
			NSString *victim =[miss objectForKey:@"victim"];
			victimhostname = [mappingGidHostname objectForKey:
									victim];
			if (victimhostname != nil){
			        NSString *vic2;
				vic2 = [NSString stringWithFormat: @"%@_at_%@",
					victim, victimhostname];
	        		NSString *dc, *t, *sc, *c, *k, *v;
				dc = [provider identifierForEntity: 
					[NSArray arrayWithObjects: @"gid", nil] 
					ids:
					[NSArray arrayWithObjects: vic2, nil]];
				t = [miss objectForKey: @"time"];
				sc = [miss objectForKey: @"sourcecontainer"];
				c = [miss objectForKey: @"container"];
				k = [miss objectForKey: @"key"];
				v = [miss objectForKey: @"value"];
	
				PajeStartLink *sl;
				sl = [[PajeStartLink alloc] init];
				[sl setTime: t];
				[sl setContainer: c];
				[sl setSourceContainer: sc];
				[sl setEntityType:
					[provider aliasToName:@"Remote_Steal"]];
				[sl setValue: v];
				[sl setKey: k];
				[ret addObject: sl];
				[sl release];
		
				PajeEndLink *el;
				el = [[PajeEndLink alloc] init];
				[el setTime: t];
				[el setContainer: c];
				[el setDestContainer: dc];
				[el setEntityType: 
					[provider aliasToName:@"Remote_Steal"]];
				[el setValue: v];
				[el setKey: k];
				[ret addObject: el];
				[el release];
				[tobetreated removeObjectAtIndex: i];
			}
		}
	}
	/* end of the check tobetreated */
	return ret;
}

- (id) convertEventKernelThreadRsteal: (GEvent *) event
{
	NSMutableArray *ret = [NSMutableArray array];
        if (conversionType == Thread){
                return ret;
        }
	[kernelRstealTimes setObject: time forKey: container];
	[ret addObject: [self addPajeSetState: @"RSTEAL"
		toState: @"State" 
		time: time
		container: container]];
	return ret;
}

- (id) convertEventKernel: (GEvent *) event
{
	NSMutableArray *ret = [NSMutableArray array];
	switch (atoi ([eventid cString])){
		case Event::CORE_THREAD_RUN:
			break;
		case Event::CORE_THREAD_COMPUTE:
			break;
		case Event::CORE_THREAD_SUSPEND:
			break;
		case Event::CORE_THREAD_WAKEUP:
			break;
		case Event::CORE_THREAD_STEAL:
			break;
		case Event::CORE_THREAD_TERM:
			break;
		case Event::CORE_THREAD_SCHED:
			break;
		case Event::CORE_THREAD_SIGNALWAKEUP:
			break;
		case Event::CORE_THREAD_LSTEAL:
			break;
		case Event::CORE_THREAD_RETLSTEAL:
			break;
		case Event::CORE_THREAD_RSTEAL:
			[ret addObjectsFromArray:
				[self convertEventKernelThreadRsteal: event]];
			break;
		case Event::CORE_THREAD_RETRSTEAL:
			[ret addObjectsFromArray: 
				[self convertEventKernelThreadRetRsteal:event]];
			break;
		case Event::CORE_PROCESSOR_IDLE0:
	[ret addObject: [self addPajeSetState: @"IDLE"
		toState: @"State" time: time container: container]];
			break;
		case Event::CORE_PROCESSOR_IDLE1:
	[ret addObject: [self addPajeSetState: @"RUNNING"
		toState: @"State" time: time container: container]];
			break;
		default:
			break;
	}
	return ret;
}
@end
